package com.loong.system.controller;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.loong.framework.dto.IdParamDTO;
import com.loong.framework.utils.CommonUtil;
import com.loong.framework.utils.SmUtil;
import com.loong.framework.utils.SystemUtil;
import com.loong.framework.vo.SelectVO;
import com.loong.system.dto.UpdateSelfDTO;
import com.loong.system.dto.UserAddDTO;
import com.loong.system.dto.UserPageDTO;
import com.loong.system.dto.UserUpdateDTO;
import com.loong.system.entity.Role;
import com.loong.system.entity.User;
import com.loong.system.service.IDictService;
import com.loong.system.service.IFileService;
import com.loong.system.service.IRoleService;
import com.loong.system.service.IUserService;
import com.loong.system.vo.UserDetailVO;
import com.loong.system.vo.UserListVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "用户操作 API")
@RestController
@RequestMapping("/api/v1.0/user")
public class UserController {

  @Resource private IUserService userService;
  @Resource private IFileService fileService;
  @Resource private IDictService dictService;
  @Resource private IRoleService roleService;

  @SaCheckRole("root")
  @Operation(summary = "新增")
  @PostMapping("/add")
  public void add(@RequestBody @Valid UserAddDTO addDTO) {
    userService.addUser(addDTO);
  }

  @SaCheckRole("root")
  @Operation(summary = "删除")
  @PostMapping("/remove")
  public void remove(@RequestBody @Valid IdParamDTO idParamDTO) {
    userService.removeUser(idParamDTO.getId());
  }

  @SaCheckRole("root")
  @Operation(summary = "更新")
  @PostMapping("/update")
  public void update(@RequestBody @Valid UserUpdateDTO updateDTO) {
    userService.updateUser(updateDTO);
  }

  @SaCheckRole("root")
  @Operation(summary = "详情")
  @PostMapping("/detail")
  public UserDetailVO detail(@RequestBody @Valid IdParamDTO idParamDTO) {
    User user = userService.getById(idParamDTO.getId());
    UserDetailVO userDetailVO = SystemUtil.buildResource(user, UserDetailVO.class);
    userDetailVO.setRoleIdList(user.getRoleIds());

    fileService.transfer(userDetailVO);
    dictService.transfer(userDetailVO);
    return userDetailVO;
  }

  @SaCheckRole(
      value = {"admin", "root"},
      mode = SaMode.OR)
  @Operation(summary = "获取用户列表")
  @PostMapping("/pageUserList")
  public Page<UserListVO> pageUserList(@RequestBody UserPageDTO userPageDTO) {
    Page<UserListVO> userList = userService.getUserList(userPageDTO);

    dictService.transfer(userList);
    fileService.transfer(userList);

    List<UserListVO> records = userList.getRecords();
    if (CommonUtil.isNullOrEmpty(records)) {
      return userList;
    }

    List<List<String>> roleIdsList = records.stream().map(UserListVO::getRoleIds).toList();
    List<String> roleIds = roleIdsList.stream().flatMap(List::stream).toList();
    List<Role> roles = roleService.listByIds(roleIds);
    if (CommonUtil.isNullOrEmpty(roles)) {
      return userList;
    }

    Map<String, String> roleId2RoleNameMap =
        roles.stream().collect(Collectors.toMap(Role::getId, Role::getRoleName));

    for (UserListVO record : records) {
      List<String> userInnerRoleIds = record.getRoleIds();
      if (CommonUtil.isNullOrEmpty(userInnerRoleIds)) {
        continue;
      }

      List<String> roleNameList = userInnerRoleIds.stream().map(roleId2RoleNameMap::get).toList();

      record.setRoleNameList(roleNameList);
    }

    return userList;
  }

  @SaCheckRole("root")
  @Operation(summary = "获取用户下拉列表")
  @PostMapping("/getUserList")
  public List<SelectVO> getUserList() {
    List<User> userList = userService.list();
    if (CommonUtil.isNullOrEmpty(userList)) {
      return new ArrayList<>();
    }

    return userList.stream().map(i -> new SelectVO(i.getNickname(), i.getId())).toList();
  }

  @Operation(summary = "获取自己的信息")
  @PostMapping("/selfInfo")
  public UserDetailVO selfInfo() {
    Object loginId = StpUtil.getLoginId();
    User user = userService.getById(loginId.toString());
    UserDetailVO userDetailVO = SystemUtil.buildResource(user, UserDetailVO.class);
    fileService.transfer(userDetailVO);
    return userDetailVO;
  }

  @Operation(summary = "更新自己的信息")
  @PostMapping("/updateSelfInfo")
  public void updateSelfInfo(@RequestBody @Valid UpdateSelfDTO updateSelfDTO) {
    User user = SystemUtil.buildResource(updateSelfDTO, User.class);
    Object loginId = StpUtil.getLoginId();
    user.setId(loginId.toString());
    String password = updateSelfDTO.getPassword();
    if (CommonUtil.notNullOrEmpty(password)) {
      user.setPassword(SmUtil.sm3(password));
    }
    userService.updateById(user);
  }
}
